package com.example.dictionary.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 磁盘空间检查工具类
 * 用于检查路径的可用空间，并选择最佳的下载位置
 */
public class DiskSpaceUtil {
    
    private static final Logger log = LoggerFactory.getLogger(DiskSpaceUtil.class);
    
    // 默认需要的最小空间：1GB
    private static final long DEFAULT_MIN_FREE_SPACE = 1024L * 1024 * 1024;
    
    /**
     * 检查路径的可用磁盘空间
     * 
     * @param path 路径
     * @param minFreeSpace 需要的最小可用空间（字节），默认 1GB
     * @return 可用空间（字节），如果检查失败返回 -1
     */
    public static long getAvailableSpace(Path path, long minFreeSpace) {
        try {
            // 确保路径的父目录存在
            Path parentPath = path.getParent();
            if (parentPath == null) {
                parentPath = path;
            }
            
            // 如果路径不存在，尝试创建父目录
            if (!Files.exists(parentPath)) {
                try {
                    Files.createDirectories(parentPath);
                } catch (IOException e) {
                    log.warn("无法创建目录: {}, 使用当前目录", parentPath);
                    parentPath = Paths.get(".");
                }
            }
            
            // 获取文件存储信息
            FileStore store = Files.getFileStore(parentPath);
            long usableSpace = store.getUsableSpace();
            
            log.debug("路径 {} 可用空间: {} MB (需要: {} MB)", 
                    parentPath, usableSpace / (1024 * 1024), minFreeSpace / (1024 * 1024));
            
            return usableSpace;
        } catch (IOException e) {
            log.warn("无法获取路径 {} 的磁盘空间: {}", path, e.getMessage());
            return -1;
        }
    }
    
    /**
     * 检查路径是否有足够的可用空间
     * 
     * @param path 路径
     * @param minFreeSpace 需要的最小可用空间（字节），默认 1GB
     * @return 是否有足够空间
     */
    public static boolean hasEnoughSpace(Path path, long minFreeSpace) {
        long availableSpace = getAvailableSpace(path, minFreeSpace);
        return availableSpace >= minFreeSpace;
    }
    
    /**
     * 检查路径是否有足够的可用空间（使用默认最小空间）
     * 
     * @param path 路径
     * @return 是否有足够空间
     */
    public static boolean hasEnoughSpace(Path path) {
        return hasEnoughSpace(path, DEFAULT_MIN_FREE_SPACE);
    }
    
    /**
     * 从多个路径中选择一个有足够空间的路径（随机选择）
     * 
     * @param paths 路径列表
     * @param minFreeSpace 需要的最小可用空间（字节），默认 1GB
     * @return 选择的路径，如果没有可用路径则返回第一个路径
     */
    public static Optional<Path> selectPathWithSpace(List<Path> paths, long minFreeSpace) {
        if (paths == null || paths.isEmpty()) {
            return Optional.empty();
        }
        
        // 检查每个路径的可用空间
        List<Path> availablePaths = paths.stream()
                .filter(path -> hasEnoughSpace(path, minFreeSpace))
                .collect(Collectors.toList());
        
        if (availablePaths.isEmpty()) {
            log.warn("所有路径都没有足够的磁盘空间，使用第一个路径: {}", paths.get(0));
            return Optional.of(paths.get(0));
        }
        
        // 随机选择一个有足够空间的路径
        Collections.shuffle(availablePaths);
        Path selectedPath = availablePaths.get(0);
        
        long availableSpace = getAvailableSpace(selectedPath, minFreeSpace);
        log.info("选择下载路径: {} (可用空间: {} MB)", 
                selectedPath, availableSpace / (1024 * 1024));
        
        return Optional.of(selectedPath);
    }
    
    /**
     * 从多个路径中选择一个有足够空间的路径（使用默认最小空间）
     * 
     * @param paths 路径列表
     * @return 选择的路径
     */
    public static Optional<Path> selectPathWithSpace(List<Path> paths) {
        return selectPathWithSpace(paths, DEFAULT_MIN_FREE_SPACE);
    }
    
    /**
     * 解析逗号分隔的路径字符串为路径列表
     * 
     * @param pathStr 路径字符串，多个路径用逗号分隔
     * @return 路径列表
     */
    public static List<Path> parsePaths(String pathStr) {
        if (pathStr == null || pathStr.trim().isEmpty()) {
            return Collections.emptyList();
        }
        
        return Arrays.stream(pathStr.split(","))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .map(Paths::get)
                .collect(Collectors.toList());
    }
    
    /**
     * 获取路径的人类可读格式（MB/GB）
     * 
     * @param bytes 字节数
     * @return 格式化字符串
     */
    public static String formatBytes(long bytes) {
        if (bytes < 1024) {
            return bytes + " B";
        } else if (bytes < 1024 * 1024) {
            return String.format("%.1f KB", bytes / 1024.0);
        } else if (bytes < 1024 * 1024 * 1024) {
            return String.format("%.1f MB", bytes / (1024.0 * 1024.0));
        } else {
            return String.format("%.1f GB", bytes / (1024.0 * 1024.0 * 1024.0));
        }
    }
}

